package com.tengju.user.infrastructure.repository;

import com.tengju.user.domain.model.sign.StarContractRepository;
import com.tengju.user.domain.model.user.*;
import com.tengju.user.domain.shared.IdObject;
import com.tengju.user.infrastructure.persistence.mybatis.dataobject.UserInfoDO;
import com.tengju.user.infrastructure.persistence.mybatis.mapper.dealer.custom.UserInfoDOCustomMapper;
import com.tengju.user.infrastructure.repository.convert.UserConvert;
import com.tengju.user.infrastructure.shared.InfraException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.tengju.user.infrastructure.repository.convert.UserConvert.encryptIdCode;

@Repository
@RequiredArgsConstructor(onConstructor_ ={@Autowired})
public class UserInfoRepositoryImpl implements UserInfoRepository {

    private final UserInfoDOCustomMapper userInfoDOCustomMapper;

    @Override
    public UserInfo getByIdCode(UserIdCode idCode) {
        if (idCode == null) {
            return null;
        }
        UserInfoDO userInfoDO = userInfoDOCustomMapper.selectByIdCode(encryptIdCode(idCode));
        return UserConvert.convertUserDOToUser(userInfoDO);
    }

    @Override
    @Transactional(value = "dealerTransactionManager", rollbackFor = Exception.class)
    public void insertOrUpdateStarInfo(UserIdCode idCode, Integer starRole, Integer starLevel) {
        userInfoDOCustomMapper.insertOrUpdateStarInfo(encryptIdCode(idCode), starRole, starLevel);
    }

    @Override
    public List<UserInfo> batchGetUserInfo(List<UserIdCode> idCodeList) {
        if (CollectionUtils.isEmpty(idCodeList)) {
            return Collections.emptyList();
        }

        List<Long> deIdCodeList = idCodeList.stream().map(UserConvert::encryptIdCode).collect(Collectors.toList());

        List<UserInfoDO> userInfoDOs = userInfoDOCustomMapper.batchGetUserInfoByIdCodes(deIdCodeList);
        return userInfoDOs.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserInfo> batchGetUserInfoByUserId(List<UserId> userIdList) {
        if (CollectionUtils.isEmpty(userIdList)) {
            return Collections.emptyList();
        }
        List<Long> userIdValList = userIdList.stream().map(IdObject::getValue).collect(Collectors.toList());

        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.batchGetUserInfoByUserId(userIdValList);
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }


    @Override
    public List<UserInfo> getByMobile(String mobile) {
        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.selectByMobileFuzzy(mobile);
        if (CollectionUtils.isEmpty(userInfoDOList)) {
            return null;
        }
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }

    @Override
    public UserInfo selectByMobile(String mobile) {

        if (mobile == null || StringUtils.isEmpty(mobile.replace(" ",""))) {
            return null;
        }
        UserInfoDO userInfoDO = userInfoDOCustomMapper.selectByMobile(mobile, mobile + "");
        if (userInfoDO == null) {
            return null;
        }
        return UserConvert.convertUserDOToUser(userInfoDO);
    }


    @Override
    public UserInfo getByAreaCodeAndMobile(String areaCode, String mobile) {
        UserInfoDO userInfoDO = userInfoDOCustomMapper.selectByAreaCodeAndMobile(areaCode, mobile);
        if (userInfoDO == null) {
            return null;
        }

        return UserConvert.convertUserDOToUser(userInfoDO);
    }

    @Override
    public UserId store(UserInfo userInfo) {

        UserInfoDO userInfoDO = UserConvert.convertUserInfoToDO(userInfo);
        userInfoDO.setCreateTime(new Date());
        userInfoDO.setUpdateTime(new Date());
        userInfoDO.setIsDelete(false);
        userInfoDOCustomMapper.insert(userInfoDO);
        return new UserId(userInfoDO.getUserId());

    }

    @Override
    public void updateUserInfo(UserInfo userInfo) {
        UserInfoDO userInfoDO = UserConvert.convertUserInfoToDO(userInfo);
        userInfoDO.setUpdateTime(new Date());
        int count = userInfoDOCustomMapper.updateUserInfo(userInfoDO);
        if (count != 1) {
            throw new InfraException("同步用户信息异常");
        }
    }

    @Override
    public void updateMobile(UserId userId, String mobile) {

        int count = userInfoDOCustomMapper.updateMobile(mobile, userId.getValue());

        if (count != 1) {
            throw new InfraException("手机号变更异常");
        }

    }

    @Override
    public void updateAreaCodeAndMobile(UserInfo userInfo) {
        UserInfoDO userInfoDO = userInfoDOCustomMapper.selectByAreaCodeAndMobile(userInfo.getAreaCode(), userInfo.getMobile());
        if (userInfoDO != null) {
            throw new InfraException("该手机号已注册");
        }
        int count = userInfoDOCustomMapper.updateAreaCodeAndMobile(userInfo.getAreaCode(), userInfo.getMobile(), userInfo.getUserId().getValue());
        if (count != 1) {
            throw new InfraException("手机号变更异常");
        }
    }

    @Override
    public UserInfo getByUserId(UserId userId) {
        if (userId == null) {
            return null;
        }
        UserInfoDO userInfoDO = userInfoDOCustomMapper.selectByUserId(userId.getValue());
        return UserConvert.convertUserDOToUser(userInfoDO);
    }

    @Override
    public void updateProtocolInfo(UserInfo userInfo) {
        UserInfoDO userInfoDO = UserConvert.convertUserInfoToDO(userInfo);
        userInfoDO.setUpdateTime(new Date());
        int count = userInfoDOCustomMapper.updateProtoInfo(userInfoDO);
        if (count != 1) {
            throw new InfraException("更新用户协议信息异常");
        }
    }

    @Override
    public void updateNickname(UserId userId, String newName) {

        int count = userInfoDOCustomMapper.updateNickname(userId.getValue(), newName, LocalDateTime.now());
        if (count != 1) {
            throw new InfraException("nickname change error");
        }

    }

    @Override
    public void updateRealName(UserIdCode idCode, String newRealName) {
        int count = userInfoDOCustomMapper.updateRealName(UserConvert.encryptIdCode(idCode), newRealName);
        if (count != 1) {
            throw new InfraException("服务商姓名修改失败! 会员id："+ idCode);
        }
    }

    @Override
    public void updateHeadImage(UserId userId, String headImage) {
        int count = userInfoDOCustomMapper.updateHeadImage(userId.getValue(), headImage, LocalDateTime.now());
        if (count != 1) {
            throw new InfraException("headImage change error");
        }

    }

    @Override
    public List<UserInfo> listAllStarUser() {
        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.listAllStarUser();
        if (CollectionUtils.isEmpty(userInfoDOList)) {
            return Collections.emptyList();
        }
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserInfo> getAll() {
        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.getAll();
        if (CollectionUtils.isEmpty(userInfoDOList)) {
            return Collections.emptyList();
        }
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserInfo> listByStarLevel(StarLevelEnum starLevel, Integer offset, Integer limit) {
        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.listByStarLevel(starLevel.getCode(), offset, limit);
        if (CollectionUtils.isEmpty(userInfoDOList)) {
            return Collections.emptyList();
        }
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserInfo> queryByStarLevel(List<StarLevelEnum> starLevels) {

        List<Integer> starLevelVals = starLevels.stream()
                .map(StarLevelEnum::getCode).collect(Collectors.toList());

        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.queryByStarLevel(starLevelVals);
        if (CollectionUtils.isEmpty(userInfoDOList)) {
            return Collections.emptyList();
        }
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }

    @Override
    public UserInfo getByUserIdCodeAndStarLevel(UserIdCode userIdCode, StarLevelEnum starLevelEnum) {
        UserInfoDO userInfoDO =
                userInfoDOCustomMapper.getByUserIdCodeAndStarLevel(encryptIdCode(userIdCode),starLevelEnum.getCode());
        return UserConvert.convertUserDOToUser(userInfoDO);
    }

    @Override
    public int countByStarLevel(List<StarLevelEnum> starLevels) {
        List<Integer> starLevelVals = starLevels.stream()
                .map(StarLevelEnum::getCode).collect(Collectors.toList());
        return userInfoDOCustomMapper.countByStarLevels(starLevelVals);
    }

    @Override
    public int countByStarLevelAndTime(List<StarLevelEnum> starLevels, LocalDateTime timeFrom, LocalDateTime timeTo) {
        List<Integer> starLevelVals = starLevels.stream()
                .map(StarLevelEnum::getCode).collect(Collectors.toList());
        return userInfoDOCustomMapper.countByStarLevels(starLevelVals);
    }

    @Override
    public void deleteByUserId(UserId userId) {
        userInfoDOCustomMapper.deleteByUserId(userId.getValue());
    }

    @Override
    public int countByForm(UserQueryForm form) {
        List<UserIdCode> idCodes = null;
        if (!CollectionUtils.isEmpty(form.getIdCodes())) {
            idCodes = form.getIdCodes().stream().map(UserConvert::encryptIdCode).map(UserIdCode::new).collect(Collectors.toList());
        }

        return userInfoDOCustomMapper.countByForm(idCodes, form.getMobile(), form.getStarLevel(), form.getOffset(), form.getPageSize());
    }

    @Override
    public List<UserInfo> batchGetByForm(UserQueryForm form) {
        List<UserIdCode> idCodes = null;
        if (!CollectionUtils.isEmpty(form.getIdCodes())) {
            idCodes = form.getIdCodes().stream().map(UserConvert::encryptIdCode).map(UserIdCode::new).collect(Collectors.toList());
        }
        List<UserInfoDO> userInfoDOList = userInfoDOCustomMapper.batchQueryByForm(idCodes, form.getMobile(), form.getStarLevel(), form.getOffset(), form.getPageSize());
        if (CollectionUtils.isEmpty(userInfoDOList)) {
            return Collections.emptyList();
        }
        return userInfoDOList.stream()
                .map(UserConvert::convertUserDOToUser)
                .collect(Collectors.toList());
    }


}
